H:\SEAMCAT\STG_30 Sept 2011 CPH\contribution to STG30 rev3\LocationProbability_rev1.java
import java.awt.Color;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;

import org.seamcat.model.plugin.*;

/**
 * 
 * 
 * {@literal }
 * 
 * <p>
 * <strong>CollectPositionData</strong> records the simulated positions of the
 * victim receiver and the levels of the wanted and unwanted signals.</br> It
 * gives the option to show the location distribution combined with dRSS, C/I,
 * C(I+N) as well as the location probability.</br> It does not change any
 * simulated result.
 * </p>
 * <p>
 * To draw the figures it uses the class StdDraw. For documentation, see Section
 * 1.5 of <i>Introduction to Programming in Java: An Interdisciplinary Approach,
 * Spring 2007 preliminary version</i> and <a href
 * ="http://www.cs.princeton.edu/introcs/15inout">http://www.cs.princeton.edu
 * /introcs/15inout</a>
 * </p>
 * 
 * @author Karl Koch <a href= "mailto: adhoc@heiseka.de">adhoc@heiseka.de</a>
 * @version rev1 26-August-2011
 * bug fix on considering the pixels below the required location probability when calculating the probabilities of exceeding the protection limit
 */
public class LocationProbability_rev1

implements PostProcessingPlugin, ConsistencyCheck { 

        private PluginDistribution defaultDistribution;
        private String filename = ""; // left empty as it is user dependent
        private String defaultPath = "";
        private String pathToSave; // combines defaultPath and filename
        private boolean shouldBeSaved = false; // flag whether the output file should be generated
        private Vector<String> outputFormat = null; // list for combobox output
        private Vector<String> outputFigure = null; // list for figure to be drawn
        private Vector<String> criterion = null; // list for the protection criterion to be used for the calculation of exceeding limits
        private int outputFormatIndex = 1; // sets .xml as default
        private int outputFigureIndex = 3; // default LP EBU
        private int criterionIndex = 1; // // default C/(I+N)
        private int currentEvent;
        private int totalEvents;
        private double[] oneShot; // used to copy not changed positions
        private String header;
        private int countVector;
        private double maxDistance = 0;
        private Transceiver rWt; // needed to record the distance between Vr and Wt
        private CollectedData singleResult = new CollectedData(); // new object containing the simulated values of a single shot
        private Vector<CollectedData> simulatedResults = null; // collects all singleResult
        private boolean multipleLinks = false;
        private double rCoverN = 20; // in dB
        private double rCoverI = 20;
        private double rIoverN = 0; 
        private double simulationRadius = 6.7; // in km
        private double locationProbability = 95.0; // in %
        private Vector<Double> rLP; // collects the calculated location probabilities
        private double minDRSS = -86.15;// dRSS required for LP = 95%
        private double STDDEV = 5.5; // standard deviation
        private double stddevInterferer = 0; // standard deviation
        private DecimalFormat df = new DecimalFormat();
        private Color notAffected;
        private String sNotAffected = "100,100,100";
        private boolean sholdShowCalculatedResults = true;
        private boolean useEBU;
        private int numberOfPixelsBelowLP;
        private int numberOfPixelsInterfered;
        private int numberOfEventsToBeConsidered;

        public void init(ParameterFactory param) {
                defaultDistribution = param.createDistribution(
                                PluginDistribution.DistributionType.PolarDistance, 0, 1);
                defaultDistribution.trial();

                /** fills the fields of the combobox */
                outputFormat = new Vector<String>();
                outputFormat.add(".txt");
                outputFormat.add(".xml");
                outputFormat.add("");

                outputFigure = new Vector<String>();
                outputFigure.add("dRSS ");
                outputFigure.add("C/I ");
                outputFigure.add("C/(N+I)");
                outputFigure.add("Location Probability (EBU)");
                outputFigure.add("dRSS Location Probability");
                outputFigure.add("Pixel distribution");
                outputFigure.add("none");

                criterion = new Vector<String>();
                criterion.add("C/I");
                criterion.add("C/(I + N)");
                criterion.add("I/N");
        }

        public void cleanUp() {
                // nothing to do  
        }

        public String getDescription() {
                return "This plug-in is to collect data in terms of positions and levels";
        }

        /**
         * method called after each snapshot = the 'heart' of the plugin :)
         */
        public void process(ScenarioInfo scenario) throws Exception {

                currentEvent = scenario.getCurrentEventNumber();

                if (currentEvent <= scenario.getNumberOfInterferingLinks()) {
                        // makes sure that all variables from the workspace are available and initializes the values                            
                        initPlugin(scenario);

                } else if (currentEvent == totalEvents) { // end of the simulation 
                        setNumberOfPixelsBelowLP(scenario);
                        setNumberOfPixelsInterfered(scenario);
                        calculateLocationProbability(scenario);
                        if (shouldBeSaved)
                                storeResults(scenario);
                        try {
                                showResults(scenario);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                } else if (currentEvent > scenario.getNumberOfInterferingLinks()) {
                        // to start collecting data with the first interfering link
                        readPosition(scenario);
                        readDRSS(scenario);
                        readIRSS(scenario);
                }

        }

        /**
         * 
         * @param scenario
         */
        private void initPlugin(ScenarioInfo scenario) {
                totalEvents = scenario.getTotalNumberOfEvents();
                setNumberOfEventsToBeConsidered(scenario);
                initWorkspace(scenario);
                if (outputFigureIndex == 3) { // EBU approach only
                        setUseEBU(true);
                } else {
                        setUseEBU(false);
                }
                /**
                 * forces the use of decimal point independent on the Locale and formats
                 * the output
                 */
                df = (DecimalFormat) DecimalFormat.getInstance(Locale.US);
                df.applyPattern("###.0#");

                simulatedResults = new Vector<CollectedData>(); // CollectedData of the data simulated

                notAffected = getColorNotAffected(sNotAffected); // may become useless

                countVector = 0; // vector to the rows of the table

                header = "event;x;y;dRSS;iRSS;noiseFloor;multiple;ilk;CoverN"; // used only for the .txt-output
                maxDistance = 0; // reset in case the simulation radius has been changed

                if (outputFormatIndex == 0 && filename.indexOf(".") == -1)
                        filename += ".txt";
                else if (outputFormatIndex == 1 && filename.indexOf(".") == -1)
                        filename += ".xml";

                if (filename.indexOf(".") == -1) {// sets xml as default in case no extension selected
                        outputFormatIndex = 1;
                        filename += ".xml";
                }
        }

        /**
         * {@literal tries to avoid an exception }
         */
        private boolean checkFilenameAndPath() {
                if (filename.equals("") || defaultPath.equals("")) {
                        return false;
                } else {
                        return true;
                }
        }

        /**
         * 
         * @param scenario
         */
        private void initWorkspace(ScenarioInfo scenario) {
                rWt = scenario.getVictimLink().getTransmitter(); // needed to get the max distance
                double radius = scenario.getVictimLink().getReceiver()
                                .getDistanceTo(rWt);
                if (radius > maxDistance)
                        maxDistance = radius; // used to scale the plot 

                rCoverN = scenario.getVictimLink().getReceiver().getRequiredCNIRatio(); // means  C/(I+N)
                rCoverI = scenario.getVictimLink().getReceiver().getRequiredCIRatio();
                rIoverN = scenario.getVictimLink().getReceiver().getRequiredINRatio();
        }

        /**
         * 
         * @param scenario
         */
        private void storeResults(ScenarioInfo scenario) {
                /** the extension of the file name defines the output format */
                String part = filename.substring(filename.indexOf(".") + 1);
                if (part.equals("txt"))
                        saveResults(scenario); // as .txt file
                else if (part.equals("xml"))
                        saveResultsXML(scenario);
                /*
                 * else if (part.equals("csv")) { saveResults(scenario); // as .csv file
                 * } // doesn't work correctly as the format is wrong
                 */
                else {
                        // TODO if other extension should be added
                }
        }

        /**
         * 
         * @param scenario
         * @throws Exception
         */
        private void showResults(ScenarioInfo scenario) throws Exception {
                /**
                 * selects the kind of figure and data to be shown as a graph
                 */
                switch (outputFigureIndex) {
                        case 0: {
                                setUseEBU(false);
                                drawDRSS_Colored(scenario);
                                break;
                        }
                        case 1: {
                                setUseEBU(false);
                                drawCoverIColored(scenario);
                                break;
                        }
                        case 2: {
                                setUseEBU(false);
                                drawCoverNplusI_Colored(scenario);
                                break;
                        }
                        case 3: {// EBU approach
                                setUseEBU(true);
                                drawLocationProbability(scenario);
                                break;
                        }
                        case 4: {
                                setUseEBU(false);
                                drawLocationProbability(scenario);
                                break;
                        }
                        case 5: {
                                setUseEBU(false);
                                drawPixelsAffected(scenario);
                                break;
                        }
                        default: {
                                setUseEBU(false);
                                // do nothing
                        }
                }
                /** show message with simulated results */
                if (sholdShowCalculatedResults) {
                        if (rLP.size() == 0)
                                calculateLocationProbability(scenario); // to ensure that LP distribution is available
                        try {
                                showSimulatedResults(scenario);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                }
        }

        private void setUseEBU(boolean useEBU) {
                this.useEBU = useEBU;

        }

        public int getNumberOfParameters() {
                return 12;
        }

        public ParameterType getParameterType(int id) {
                switch (id) {
                        case 1: {
                                return ParameterType.String; // filename for the output
                        }
                        case 2: {
                                return ParameterType.String; // default path for the output files
                        }
                        case 3: {
                                return ParameterType.Integer; // outputFormatIndex
                        }
                        case 4: {
                                return ParameterType.Boolean; // flag to save output
                        }
                        case 5: {
                                return ParameterType.Integer; // flag for drawing the figure
                        }
                        case 6: {
                                return ParameterType.Double; // simulation radius
                        }
                        case 7: {
                                return ParameterType.Double; // location probability
                        }
                        case 8: {
                                return ParameterType.Double; // dRSS
                        }
                        case 9: {
                                return ParameterType.Double; // stddev of dRSS
                        }
                        case 10: {
                                return ParameterType.Double; // stddev of interferer
                        }
                        case 11: {
                                return ParameterType.Integer; // to protection criterion
                        }
                        case 12: {
                                return ParameterType.Boolean; // flag to showing calculated results
                        }
                        default: {
                                throw new IllegalArgumentException("illegal parameter id");
                        }

                }
        }

        public void setParameterValue(int id, Object value) {
                try {
                        switch (id) {
                                case 1: {
                                        this.filename = (String) value;
                                        break;
                                }
                                case 2: {
                                        this.defaultPath = (String) value;
                                        break;
                                }
                                case 3: {
                                        this.outputFormatIndex = (Integer) value;
                                        break;
                                }
                                case 4: {
                                        this.shouldBeSaved = (Boolean) value;
                                        break;
                                }
                                case 5: {
                                        this.outputFigureIndex = (Integer) value;
                                        break;
                                }
                                case 6: {
                                        this.simulationRadius = (Double) value;
                                        break;
                                }
                                case 7: {
                                        this.locationProbability = (Double) value;
                                        break;
                                }
                                case 8: {
                                        this.minDRSS = (Double) value;
                                        break;
                                }
                                case 9: {
                                        this.STDDEV = (Double) value;
                                        break;
                                }
                                case 10: {
                                        this.stddevInterferer = (Double) value;
                                        break;
                                }
                                case 11: {
                                        this.criterionIndex = (Integer) value;
                                        break;
                                }
                                case 12: {
                                        this.sholdShowCalculatedResults = (Boolean) value;
                                        break;
                                }
                                default: {
                                        throw new IllegalArgumentException("illegal parameter id");
                                }
                        }
                } catch (Exception e) {

                }
        }

        public Object getParameterValue(int id) {
                switch (id) {
                        case 1: {
                                return this.filename;
                        }
                        case 2: {
                                return this.defaultPath;
                        }
                        case 3: {
                                return this.outputFormatIndex;
                        }
                        case 4: {
                                return this.shouldBeSaved;
                        }
                        case 5: {
                                return this.outputFigureIndex;
                        }
                        case 6: {
                                return this.simulationRadius;
                        }
                        case 7: {
                                return this.locationProbability;
                        }
                        case 8: {
                                return this.minDRSS;
                        }
                        case 9: {
                                return this.STDDEV;
                        }
                        case 10: {
                                return this.stddevInterferer;
                        }
                        case 11: {
                                return this.criterionIndex;
                        }
                        case 12: {
                                return this.sholdShowCalculatedResults;
                        }
                        default: {
                                throw new IllegalArgumentException("illegal parameter id");
                        }

                }
        }

        public String getParameterName(int id) {
                switch (id) {
                        case 1: {
                                return "file name of the output data";
                        }

                        case 2: {
                                return "default path ";
                        }
                        case 3: {
                                return "output format ";
                        }

                        case 4: {
                                return "save output file ";
                        }
                        case 5: {
                                return "parameter to be drawn";
                        }

                        case 6: {
                                return "simulation radius  [km]";
                        }
                        case 7: {
                                return "location probability [%]";
                        }
                        case 8: {
                                return "minimum wanted Signal  [dBm]";
                        }
                        case 9: {
                                return "standard deviation of the wanted signal [dB]";
                        }
                        case 10: {
                                return "standard deviation of the interfering signal [dB]";
                        }
                        case 11: {
                                return "protection criterion to be used for limit calculations";
                        }
                        case 12: {
                                return "show calculated results ";
                        }
                        default: {
                                throw new IllegalArgumentException("illegal parameter id");
                        }

                }
        }

        /* check consistency of the workspace */
        public boolean check(ScenarioInfo scenario) {
                boolean checkPropagationModel = true;
                String warning = "<html><br>";
                warning += "<br/><br/><strong>Post Processing Plugin: </strong>";
                warning += "<br />Please ensure that the values of <br/><strong>C/I, C/(I+N) and I/N</strong><br/>"
                                + "are defined as you want, even if there is still a consitency warning."
                                + "<br>";

                if (shouldBeSaved && !checkFilenameAndPath()) {
                        filename = "outputData.xml";
                        defaultPath = "C:";
                        pathToSave = defaultPath + "\\" + filename;
                        warning += "<br />Due to the location for the output files has not been defined,<br />the collected data will be saved onto <strong>"
                                        + pathToSave
                                        + "</strong> <br /> and the corresponding DTD onto <strong>C:\\result.dtd</strong>";

                }
                checkPropagationModel = false;
                warning += "</html>";

                if (checkPropagationModel == false) {
                        scenario.addConsistencyWarning(warning); 
                        return false;
                } else {
                        return true;
                }
        }

        @Override
        public Vector<String> getAllowedParameterValues(int index) {

                switch (index) {
                        case 3:
                                return this.outputFormat;

                        case 5:
                                return this.outputFigure;

                        case 11:
                                return this.criterion;

                }
                return null;
        }

        /**
         * methods added
         * 
         */
        
        
        /**
         * {@literal adds the current event number and the positions x and y of the victim to the current row; }
         * {@literal oneShot[] collects the values of event, x, y and dRSS which are not changed in case different interfering links have to be considered}
         * 
         * @param scenario
         */
        private void readPosition(ScenarioInfo scenario) {
                oneShot = new double[4]; // reset to zero
                oneShot[0] = currentEvent;
                oneShot[1] = scenario.getVictimLink().getReceiver().getPositionX();
                oneShot[2] = scenario.getVictimLink().getReceiver().getPositionY();
                double radius = scenario.getVictimLink().getReceiver()
                                .getDistanceTo(rWt);
                if (radius > maxDistance)
                        maxDistance = radius; // updates the max distance simulated; needed for the correct scaling of the plot 
        }

        /**
         * {@literal adds the dRSS to the current row}
         * 
         * @param scenario
         */
        private void readDRSS(ScenarioInfo scenario) {
                oneShot[3] = scenario.getVictimLink().getDRSSValue();
        }

        /**
         * {@literal adds the iRSS and the index of the interfering link to the table; }
         * {@literal in case more than one interfering link exist the values for event, x, y and dRSS are copied}
         * 
         * @param scenario
         * @throws Exception
         */
        private void readIRSS(ScenarioInfo scenario) {
                List<InterferingLink> ilks = scenario.getInterferingLinks();
                if (scenario.getNumberOfInterferingLinks() == 1)
                        multipleLinks = false;
                else
                        multipleLinks = true;
                for (InterferingLink link : ilks) {
                        singleResult = new CollectedData();
                        singleResult.event = (int) oneShot[0];
                        singleResult.x = oneShot[1];
                        singleResult.y = oneShot[2];
                        singleResult.dRSS = oneShot[3];
                        singleResult.iRSS = link.getIRSSUnwanted();
                        singleResult.cOverI = Math.abs(singleResult.dRSS
                                        - singleResult.iRSS);
                        singleResult.noiseFloor = getNoiseFloor(scenario);
                        //                      singleResult.noiseFloor = noiseFloor;
                        singleResult.isMultipleILK = multipleLinks;
                        singleResult.ilk = link.getLinkIndex();
                        try {
                                singleResult.cOverN = getCoverNplusI(scenario);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                        singleResult.cIverN = getIoverN(scenario);
                        simulatedResults.add(singleResult);
                        countVector++; // Counter for the rows of the resulting table
                }

        }

        private double getNoiseFloor(ScenarioInfo scenario) {
                return scenario.getVictimLink().getReceiver().getNoiseFloor().trial();
        }

        /**
         * {@literal stores the generated table as text file }
         * 
         * @param scenario
         */
        private void saveResults(ScenarioInfo scenario) {
                pathToSave = defaultPath + "\\" + filename;
                int fSize = (int) (scenario.getNumberOfInterferingLinks() * 6 * 20
                                * totalEvents / 1024.0 / 1024.0 + 1); // 
                ProgressBarStoreFile progressstore = new ProgressBarStoreFile(
                                "Saving TXT file in progress (about " + fSize + " MB)");
                progressstore.init();
                progressstore.progressBar.setMinimum(0);
                progressstore.progressBar.setMaximum(countVector);
                try {
                        BufferedWriter out = new BufferedWriter(new FileWriter(pathToSave));

                        out.write(header); // header of the columns of the table 
                        out.newLine();

                        for (int i = 0; i < countVector; i++) {
                                out.write(simulatedResults.get(i).event + ";");
                                out.write(simulatedResults.get(i).x + ";");
                                out.write(simulatedResults.get(i).y + ";");
                                out.write(simulatedResults.get(i).dRSS + ";");
                                out.write(simulatedResults.get(i).iRSS + ";");
                                out.write(simulatedResults.get(i).noiseFloor + ";");
                                out.write(simulatedResults.get(i).isMultipleILK + ";");
                                out.write(simulatedResults.get(i).ilk + ";");
                                out.write(simulatedResults.get(i).cOverN + "");
                                out.newLine();
                                progressstore.progressBar.setValue(i + 1);
                        }
                        out.flush();
                        out.close();
                        progressstore.stop();
                } catch (IOException e) {
                        e.printStackTrace();
                }

        }

        /**
         * {@literal saveResultsXML stores the result as XML file}
         */
        private void saveResultsXML(ScenarioInfo scenario) {
                pathToSave = defaultPath + "\\" + filename;
                int fSize = (int) (scenario.getNumberOfInterferingLinks() * 7 * 32
                                * totalEvents / 1024.0 / 1024.0 + 1); // seven columns each 32 bytes
                ProgressBarStoreFile progressstore = new ProgressBarStoreFile(
                                "Saving XML file in progress (about " + fSize + " MB)");
                progressstore.init();
                progressstore.progressBar.setMinimum(0);
                progressstore.progressBar.setMaximum(countVector);
                try {
                        BufferedWriter out = new BufferedWriter(new FileWriter(pathToSave));
                        String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>";
                        String xmlRoot = "result";
                        String xmlElement = "event";

                        out.write(xmlDeclaration);
                        out.newLine();
                        out.write("<" + xmlRoot + ">");
                        out.newLine();
                        for (int i = 0; i < countVector; i++) {
                                String element = "<" + xmlElement;
                                element += " eventNr = \"" + simulatedResults.get(i).event;
                                element += " \" x = \"" + simulatedResults.get(i).x;
                                element += " \" y = \"" + simulatedResults.get(i).y;
                                element += " \" dRSS = \"" + simulatedResults.get(i).dRSS;
                                element += " \" iRSS = \"" + simulatedResults.get(i).iRSS;
                                element += " \" noiseFloor = \""
                                                + simulatedResults.get(i).noiseFloor;
                                element += " \" multiple = \""
                                                + simulatedResults.get(i).isMultipleILK;
                                element += " \" ilk = \"" + simulatedResults.get(i).ilk;
                                element += " \" CoverI = \"" + simulatedResults.get(i).cOverN
                                                + "\">";
                                element += "</" + xmlElement + ">";
                                out.write(element);
                                out.newLine();
                                progressstore.progressBar.setValue(i + 1);
                        }
                        out.write("</" + xmlRoot + ">");
                        out.flush();
                        out.close();
                        storeDTD(); // saves the corresponding xml namespace as result.dtd
                        progressstore.stop();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }

        /**
         * {@literal storeDTD generates the DTD needed for the above XML file to that path the result has been saved}
         */
        private void storeDTD() {
                try {
                        BufferedWriter out = new BufferedWriter(new FileWriter(defaultPath
                                        + "\\result.dtd"));
                        String DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <!ELEMENT result ((event+))> <!ELEMENT event EMPTY>"
                                        + "<!ATTLIST event      dRSS CDATA #REQUIRED    eventNr CDATA #REQUIRED "
                                        + "     iRSS CDATA #REQUIRED    noiseFloor CDATA #REQUIRED ilk CDATA #REQUIRED  x CDATA #REQUIRED       y CDATA #REQUIRED CoverI CDATA #REQUIRED multiple CDATA #REQUIRED>";

                        out.write(DTD);
                        out.flush();
                        out.close();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }

        /**
         * {@literal draws a figure using the class StdDraw} For additional
         * documentation, see <a
         * href="http://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
         * <i>Introduction to Programming in Java: An Interdisciplinary Approach</i>
         * by Robert Sedgewick and Kevin Wayne.
         * 
         */

        /**
         * {@literal calculates the location probability of a pixel and collects is on a vector}
         * 
         * @param scenario
         * @throws Exception
         */
        private void calculateLocationProbability(ScenarioInfo scenario)
                        throws Exception {
                rLP = new Vector<Double>();
                double testDRSS;
                double deltaFactor = 0;
                double percentage;
                double tCoverNplusI = 0;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        testDRSS = simulatedResults.get(i).dRSS;
                        if (!simulatedResults.firstElement().isMultipleILK) {// single interfering link
                                if (isUseEBU()) { // use the EBU approach considering C/(I+N)                   
                                        double tIRSS = simulatedResults.get(i).iRSS;
                                        tCoverNplusI = 10 * Math
                                                        .log10(Math.pow(10, (testDRSS / 10))
                                                                        / (Math.pow(10,
                                                                                        (simulatedResults.get(i).iRSS / 10)) + Math.pow(
                                                                                        10,
                                                                                        (simulatedResults.get(i).noiseFloor / 10))));

                                        deltaFactor = tCoverNplusI - rCoverN;
                                } else { // only dRSS
                                        deltaFactor = testDRSS - minDRSS;
                                }
                        } else {
                                if (isUseEBU()) { // use the EBU approach considering C/(I+N)   
                                        tCoverNplusI = 10 * Math
                                                        .log10(Math.pow(10, (testDRSS / 10))
                                                                        / (Math.pow(
                                                                                        10,
                                                                                        (getSumOfInterfernce(i, scenario) / 10.)) + Math.pow(
                                                                                        10,
                                                                                        (simulatedResults.get(i).noiseFloor / 10))));
                                        deltaFactor = tCoverNplusI - rCoverN;
                                } else { // only dRSS
                                        deltaFactor = testDRSS - minDRSS;
                                }
                                i += scenario.getNumberOfInterferingLinks() - 1; // jumps to the next pixel
                        }
                        // in case stddev of interferer should be considered
                        double rSTDEEVcombined = Math.sqrt(STDDEV * STDDEV
                                        + stddevInterferer * stddevInterferer);
                        deltaFactor /= rSTDEEVcombined;

                        percentage = getPercentageSevenTrials(deltaFactor); // iterative approach

                        if (isUseEBU()) {
                                if (tCoverNplusI <= 0)
                                        percentage = 0; // 
                        } else {
                                //      percentage = 100 - percentage; // as the location probability of the wanted signal
                        }
                        rLP.add(percentage);
                }
        }

        /**
         * 
         * @param i
         *            actual pixel index
         * @param scenario
         * @return integrated iRSS
         */
        private double getSumOfInterfernce(int i, ScenarioInfo scenario) {
                double sumOfInterference = 0;
                for (int j = 0; j < scenario.getNumberOfInterferingLinks(); j++) {
                        sumOfInterference += Math.pow(10,
                                        (simulatedResults.get(i + j).iRSS) / 10);
                }
                return 10 * Math.log10(sumOfInterference);
        }

        /**
         * 
         * @return flag whether EBU approach should be used
         */
        private boolean isUseEBU() {
                return this.useEBU;
        }

        /**
         * 
         * @return highest value of location probability calculated
         */
        private double getMaxLP() {
                double maxLP = 0;
                for (int i = 0; i < rLP.size(); i++) {
                        if (rLP.get(i) > maxLP) {
                                maxLP = rLP.get(i);
                        }
                }
                return maxLP;
        }

        /**
         * 
         * @param scenario
         * @param j
         *            current pixel ID
         * @return corresponds to whether affected or not and defines the colour
         */
        private int getPixelStatus(ScenarioInfo scenario, int j) {
                int rStatus = 2;
                if (simulatedResults.get(j).dRSS < minDRSS) {
                        rStatus = 0;// not affected
                } else if (!simulatedResults.get(j).isInterfered) {
                        rStatus = 1; // green
                } else if (simulatedResults.get(j).isInterfered) {
                        rStatus = 2; // red
                }
                return rStatus;
        }

        /**
         * {@literal shows a message with simulated results }
         * 
         * @param scenario
         * @throws Exception
         */
        private void showSimulatedResults(ScenarioInfo scenario) throws Exception {
                if (rLP.size() == 0)
                        calculateLocationProbability(scenario); // to ensure that LP distribution is available

                String msg = "Pixels not meeting min dRSS:     "
                                + getNumberOfPixelsBelowLP() + "\n";
                msg += "Pixels with interferer:                 "
                                + getNumberOfPixelsInterfered() + "\n";
                msg += "Number of pixels generated:      "
                                + getNumberOfEventsToBeConsidered()
                                + " ("
                                + (df.format(getNumberOfEventsToBeConsidered()
                                                / (maxDistance * maxDistance * Math.PI)))
                                + "/sqkm)\n\n";
                msg += "Probability of exceeding the limit of "
                                + criterion.get(criterionIndex)
                                + " = "
                                + df.format(getCriterionLimit())
                                + " dB due to interference:   "
                                + (df.format((double) ((getNumberOfPixelsInterfered())
                                                / (double) (getNumberOfEventsToBeConsidered() - getNumberOfPixelsBelowLP()) * 100.0)))
                                + "%\n";
                msg += "\nPercentage below minimum wanted Signal level:    "
                                + (df.format((double) ((getNumberOfPixelsBelowLP())
                                                / (double) (getNumberOfEventsToBeConsidered()) * 100.0)))
                                + "%";
                if (isUseEBU()) {
                        double degradation = ((double) (getNumberOfPixelsNotMeetingLP() - getNumberOfPixelsBelowLP()) / (double) (getNumberOfEventsToBeConsidered() - getNumberOfPixelsBelowLP())) * 100;

                        msg += "\nDegradation of location probability of "
                                        + locationProbability + "%:          "
                                        + (df.format(degradation)) + "%";
                }
                msg += "         ";// to expand the width

                JFrame frame = new JFrame("Simulation results");
                frame.setResizable(true);
                frame.setSize(400, 400);
                JOptionPane.showMessageDialog(frame, msg,
                                "Simulation result of post processsing (LP="
                                                + locationProbability + "%)",
                                JOptionPane.INFORMATION_MESSAGE);
        }

        /**
         * 
         * @return total number of pixels below required LP
         */
        private int getNumberOfPixelsNotMeetingLP() {
                int k = 0;
                for (int i = 0; i < rLP.size(); i++) {
                        if (rLP.get(i) < locationProbability) {
                                k++;
                        }
                }
                return k;
        }

        /**
         * 
         * @param scenario
         * @return number of pixels not meeting the limit caused only by noise floor
         * @throws Exception
         */
        private int getNumberOfPixelsEmpty(ScenarioInfo scenario) throws Exception {
                int k = 0;
                if (!simulatedResults.firstElement().isMultipleILK) { // single interfering link
                        for (int i = 0; i < simulatedResults.size(); i++) {
                                if (simulatedResults.get(i).dRSS <= minDRSS) { // changed to <= instead of <
                                        k++;
                                }
                        }
                } else {
                        for (int i = 0; i < simulatedResults.size(); i++) {
                                if (simulatedResults.get(i).dRSS <= minDRSS) {// changed to <= instead of <
                                        k++;
                                        i += scenario.getNumberOfInterferingLinks() - 1; // skips to next pixel
                                }
                        }
                }
                return k;
        }

        /**
         * 
         * @param scenario
         * @return number of pixels not meeting the limit
         */
        private int getNumberOfPixelsInterfered(ScenarioInfo scenario) {
                int k = 0;

                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (!simulatedResults.firstElement().isMultipleILK) {// single interfering link
                                if (getLimitExceeded(i)) {
                                        k++;
                                }
                        } else {// more than one interfering link
                                if (getLimitExceededMultiple(i, scenario)) {
                                        k++;
                                }
                                i += scenario.getNumberOfInterferingLinks() - 1; // jumps to next pixel
                        }
                }
                return k;
        }

        private boolean getLimitExceededMultiple(int i, ScenarioInfo scenario) {
                // TODO Auto-generated method stub
                double sumOfInterference = getSumOfInterfernce(i, scenario);
                if (getLimitExceeded(i, sumOfInterference)) {
                        simulatedResults.get(i).isInterfered = true;
                        return true;
                } else {
                        simulatedResults.get(i).isInterfered = false;
                        return false;
                }
        }

        /**
         * {@literal shows a colour scaled distribution of C/I}
         * 
         * @param scenario
         */
        private void drawCoverIColored(ScenarioInfo scenario) {
                scaleFigure();
                double highestCoverI = getHighestCoverI();
                double lowestCoverI = getLowestCoverI();
                double rCoverI = 0;
                double range = Math.abs(highestCoverI - lowestCoverI);

                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (!simulatedResults.get(i).isMultipleILK) {
                                rCoverI = simulatedResults.get(i).cOverI;
                        } else {
                                rCoverI = getCoverImultiple(scenario, i); // gets the lowest CoverI for that pixel
                                i += scenario.getNumberOfInterferingLinks() - 1;
                        }

                        Color colorAtIndex = getColor(rCoverI - lowestCoverI, range);
                        StdDraw.setPenColor(colorAtIndex);

                        StdDraw.filledSquare(simulatedResults.get(i).x,
                                        simulatedResults.get(i).y, 0.05, false);
                }

                /** legend */
                drawScaling(lowestCoverI, highestCoverI, maxDistance, 20, " dB");
                StdDraw.setPenColor(StdDraw.BLACK);
                StdDraw.text(0, 1.05 * maxDistance, "C/I distribution");
                StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                + df.format(maxDistance) + " km");
                StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                (totalEvents - scenario.getNumberOfInterferingLinks())
                                                + " events");

                if (scenario.getNumberOfInterferingLinks() > 1) {
                        StdDraw.text(0.8 * maxDistance, -1 * maxDistance,
                                        scenario.getNumberOfInterferingLinks()
                                                        + " interfering links");
                }
                StdDraw.show();
        }

        /**
         * {@literal shows a colour scaled distribution of C/(N+I)}
         * 
         * @param scenario
         */
        private void drawCoverNplusI_Colored(ScenarioInfo scenario) {

                scaleFigure();

                double lowestCoverN = getLowestCoverN();
                double highestCoverN = getHighestCoverN();
                double range = highestCoverN - lowestCoverN;
                double testCoverN = 0;

                for (int i = 0; i < simulatedResults.size(); i++) {
                        testCoverN = simulatedResults.get(i).cOverN;
                        if (simulatedResults.firstElement().isMultipleILK) {// more than one interfering link
                                int j = 1;
                                do {
                                        if (simulatedResults.get(i + j).cOverN < testCoverN) {
                                                testCoverN = simulatedResults.get(i + j).cOverN;
                                                j++;
                                        } else {
                                                j++;
                                        }
                                } while (j < scenario.getNumberOfInterferingLinks());
                                i += scenario.getNumberOfInterferingLinks() - 1; // skips to the next pixel
                        }
                        Color colorAtIndex = getColor(testCoverN - lowestCoverN, range);
                        StdDraw.setPenColor(colorAtIndex);
                        StdDraw.filledSquare(simulatedResults.get(i).x,
                                        simulatedResults.get(i).y, 0.05, false);
                }

                /** legend */
                drawScaling(lowestCoverN, highestCoverN, maxDistance, rCoverN, " dB");
                StdDraw.setPenColor(StdDraw.BLACK);
                StdDraw.text(0, 1.05 * maxDistance, "C/(N+I) distribution");
                StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                + df.format(maxDistance) + " km");
                StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                (totalEvents - scenario.getNumberOfInterferingLinks())
                                                + " events");

                if (scenario.getNumberOfInterferingLinks() > 1) {
                        StdDraw.text(0.8 * maxDistance, -1 * maxDistance,
                                        scenario.getNumberOfInterferingLinks()
                                                        + " interfering links");
                }
                StdDraw.show();

        }

        /**
         * {@literal draws a colour scaled map of the dRSS distribution}
         * 
         * @param scenario
         */
        private void drawDRSS_Colored(ScenarioInfo scenario) {
                scaleFigure();

                double lowestDRSSS = getLowestDRSS();
                double highestDRSSS = getHighestDRSS();
                double range = highestDRSSS - lowestDRSSS;

                for (int i = 0; i < simulatedResults.size(); i++) {
                        Color colorAtIndex = getColor(simulatedResults.get(i).dRSS
                                        - lowestDRSSS, range);
                        StdDraw.setPenColor(colorAtIndex);
                        StdDraw.filledSquare(simulatedResults.get(i).x,
                                        simulatedResults.get(i).y, 0.04, false);
                }
                /** legend */
                drawScaling(getLowestDRSS(), getHighestDRSS(), maxDistance, -77.1,
                                " dBm");
                StdDraw.setPenColor(StdDraw.BLACK);
                StdDraw.text(0, 1.05 * maxDistance, "dRSS distribution");
                StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                + df.format(maxDistance) + " km");
                StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                (totalEvents - scenario.getNumberOfInterferingLinks())
                                                + " events");
                StdDraw.show();

        }

        /**
         * {@literal shows a colour scaled distribution of the dRSS location probability}
         * 
         * @param scenario
         */
        private void drawLocationProbability(ScenarioInfo scenario) {
                scaleFigure();
                double lowestLPnotZero = getLowestLPnotZero();
                double maxLP = getMaxLP();
                double range = maxLP - lowestLPnotZero;
                int j = -1; // increased to zero on the first step of the loop
                for (int i = 0; i < simulatedResults.size(); i++) {
                        j++;
                        double percentage = rLP.get(j);

                        StdDraw.setPenColor(getColor(percentage - lowestLPnotZero, range));

                        if (percentage < locationProbability
                                        && simulatedResults.get(i).iRSS > minDRSS && isUseEBU()) {
                                StdDraw.setPenColor(StdDraw.WHITE);
                        }

                        StdDraw.filledSquare(simulatedResults.get(i).x,
                                        simulatedResults.get(i).y, 0.04, false);
                        if (simulatedResults.firstElement().isMultipleILK) { // jumps to the next pixel
                                i += scenario.getNumberOfInterferingLinks() - 1;
                        }
                }

                drawScaling(lowestLPnotZero, maxLP, maxDistance, locationProbability,
                                "%");
                String assumedModelName = scenario.getVictimLink()
                                .getPropagationModel().getAssumedModel().name();
                if (assumedModelName.equals("NoModelDefined")) {
                        assumedModelName = "User-defined dRSS";
                }
                StdDraw.setPenColor(StdDraw.BLACK);
                if (!isUseEBU()) {
                        double resultingLP = (double) (100 - (getNumberOfPixelsBelowLP())
                                        / (double) (getNumberOfEventsToBeConsidered()) * 100);
                        StdDraw.text(0, 1.11 * maxDistance,
                                        "dRSS Location Propability distribution - "
                                                        + assumedModelName);
                        StdDraw.text(0, 1.05 * maxDistance,
                                        "Resulting Coverage Propability " + df.format(resultingLP)
                                                        + "%");
                } else {
                        double degradation = ((double) (getNumberOfPixelsNotMeetingLP() - getNumberOfPixelsBelowLP()) / (double) (getNumberOfEventsToBeConsidered() - getNumberOfPixelsBelowLP())) * 100;

                        StdDraw.text(
                                        0,
                                        1.11 * maxDistance,
                                        "Location Propability distribution for "
                                                        + (df.format((double) (100 - (getNumberOfPixelsBelowLP())
                                                                        / (double) (getNumberOfEventsToBeConsidered())
                                                                        * 100.0))) + "% coverage - "
                                                        + assumedModelName);
                        StdDraw.text(
                                        0,
                                        1.05 * maxDistance,
                                        "Location Propability degradation relative to "
                                                        + locationProbability + "%  =  "
                                                        + df.format(degradation) + "%");
                }
                StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                + df.format(maxDistance) + " km");
                StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                (totalEvents - scenario.getNumberOfInterferingLinks())
                                                + " events");

                /*              if (isUseEBU()) {
                                        double degradation =
                                                        ((double) (getNumberOfPixelsNotMeetingLP() - getNumberOfPixelsBelowLP()) / (double) (getNumberOfEventsToBeConsidered())) * 100;
                                        StdDraw.text(-0.85 * maxDistance, -0.98 * maxDistance,
                                                        "Location Propability degradation: " + df.format(degradation) + "%");
                                }*/

                StdDraw.show();

        }

        /**
         * {@literal shows pixels not affected, interfered and not interfered}
         * 
         * @param scenario
         */
        private void drawPixelsAffected(ScenarioInfo scenario) {
                scaleFigure();
                int pixelStatus = 0; // not affected
                Color[] colorStatus = new Color[] { notAffected, new Color(0, 255, 0),
                                StdDraw.RED };

                int k = 0;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (!simulatedResults.firstElement().isMultipleILK) {// single interfering link 
                                pixelStatus = getPixelStatus(scenario, i);
                                k = i;
                        } else {
                                if (simulatedResults.get(i).isInterfered) {
                                        pixelStatus = 2;
                                        k = i;
                                        i += scenario.getNumberOfInterferingLinks() - 1;
                                } else {
                                        pixelStatus = 0;
                                        int j = 0;
                                        do {
                                                if (pixelStatus < getPixelStatus(scenario, (i + j))) {
                                                        pixelStatus = getPixelStatus(scenario, (i + j));
                                                        k = i + j;
                                                        j++;
                                                } else {
                                                        j++;
                                                }
                                        } while (j < scenario.getNumberOfInterferingLinks());
                                        i += scenario.getNumberOfInterferingLinks() - 1;
                                }
                        }
                        StdDraw.setPenColor(colorStatus[pixelStatus]);
                        StdDraw.filledSquare(simulatedResults.get(k).x,
                                        simulatedResults.get(k).y, 0.05, false);
                }

                /* legend */
                StdDraw.setPenColor(colorStatus[0]);
                StdDraw.text(-0.9 * maxDistance, -1 * maxDistance, "LP below "
                                + locationProbability + "%");
                StdDraw.setPenColor(colorStatus[1]);
                StdDraw.text(-0.9 * maxDistance, -0.95 * maxDistance, "not interfered");
                StdDraw.setPenColor(colorStatus[2]);
                StdDraw.text(-0.9 * maxDistance, -0.90 * maxDistance, "interfered");
                StdDraw.setPenColor(StdDraw.BLACK);
                StdDraw.text(0, 1.1 * maxDistance, "Pixel distribution - LP = "
                                + locationProbability + "%");
                StdDraw.text(0, 1.05 * maxDistance, "Interference criterion: "
                                + criterion.get(criterionIndex));
                StdDraw.text(0.8 * maxDistance, -0.9 * maxDistance, " max distance "
                                + df.format(maxDistance) + " km");
                StdDraw.text(0.8 * maxDistance, -0.95 * maxDistance,
                                (totalEvents - scenario.getNumberOfInterferingLinks())
                                                + " events");
                if (scenario.getNumberOfInterferingLinks() > 1) {
                        StdDraw.text(0.8 * maxDistance, -1 * maxDistance,
                                        scenario.getNumberOfInterferingLinks()
                                                        + " interfering links");
                } /*else {
                        StdDraw.text(0.0 * maxDistance, -1.05 * maxDistance, scenario.getInterferingLink(1).getTransmitter()
                                        .getSuppliedPower()
                                        + " dBm");
                        }*/
                StdDraw.setPenColor(StdDraw.CYAN);
                StdDraw.circle(0, 0, simulationRadius);
                StdDraw.setPenColor(StdDraw.DARK_GRAY);
                StdDraw.circle(0, 0, maxDistance);
                StdDraw.show();
        }

        /**
         * 
         * @param lowest
         * @param max
         * @param distance
         * @param reference
         *            if zero: ignored
         * @param s
         *            = dimension of the parameter, e.g. % for probability
         */
        private void drawScaling(double lowest, double max, double distance,
                        double reference, String s) {
                Color rDot;
                double x0 = -0.95 * maxDistance;
                double y0 = -1.08 * maxDistance;
                double y = 0.025;
                double x = 0.2;

                for (int i = 0; i < 512; i++) {
                        rDot = getColor(i, 512);
                        StdDraw.setPenColor(rDot);
                        StdDraw.line(x0 + i * y, y0, x0 + i * y, y0 + x, false);
                }

                StdDraw.setPenColor(new Color(0, 0, 255));
                StdDraw.text(1.15 * x0, y0, df.format(lowest) + s);
                StdDraw.setPenColor(new Color(0, 255, 0));
                StdDraw.text(x0 + 545 * y, y0, df.format(max) + s);
                if (reference != 0) {
                        // FIX
                        if (max == lowest) {
                                if (max < reference)
                                        max = reference;
                                else
                                        lowest = reference;
                        }
                        StdDraw.setPenColor(getColor((reference - lowest), (max - lowest)));
                        StdDraw.text(x0 + 512 * (reference - lowest) / (max - lowest) * y,
                                        y0 + 2 * x, df.format(reference) + s);
                }

                StdDraw.setPenColor(StdDraw.CYAN);
                StdDraw.circle(0, 0, simulationRadius);
                StdDraw.setPenColor(StdDraw.DARK_GRAY);
                StdDraw.circle(0, 0, maxDistance);

        }

        /**
         * 
         * @param value
         *            to be scaled
         * @param range
         *            of scaling
         * @return corresponding colour red and blue combined
         */
        private Color getColor(double value, double range) {
                Color rColor = new Color(0, 0, 0);
                double i = ((value / range) * 511);
                if (value == 0)
                        i = 0;
                if (i > 255) {
                        return rColor = getColorGreen(i);
                }
                if (i <= 255) {
                        if (value < 0) {
                                rColor = new Color(255, 255, 255);
                        } else {
                                rColor = new Color((int) (i), 0, 255 - (int) (i));
                        }
                }
                return rColor;
        }

        /**
         * 
         * @param value
         *            to be scaled
         * @return corresponding colour including green
         */
        private Color getColorGreen(double value) {
                Color rColor;
                int i = (int) (value - 256);
                if (value < 0) {
                        rColor = new Color(255, 255, 255);
                } else {
                        rColor = new Color(255 - i, i, 0);
                }
                return rColor;
        }

        /**
         * {@literal mainly a place marker }
         * 
         * @param color
         * @return defined colour
         */
        private Color getColorNotAffected(String color) {
                String[] colors = color.split(",");
                int red = Integer.parseInt(colors[0]);
                int green = Integer.parseInt(colors[1]);
                int blue = Integer.parseInt(colors[2]);
                return new Color(red, green, blue);
        }

        /**
         * 
         * @param scenario
         * @param i
         *            pixel to be checked
         * @return lowest C/I of this pixel
         */
        private double getCoverImultiple(ScenarioInfo scenario, int i) {
                double tCoverI = simulatedResults.get(i).cOverI;
                int j = 1; // selects the next link
                do {
                        if (simulatedResults.get(i + j).cOverI < tCoverI) {
                                tCoverI = simulatedResults.get(i + j).cOverI;
                                j++;// selects the next link
                        } else {
                                j++;// selects the next link
                        }
                } while (j < scenario.getNumberOfInterferingLinks());

                return tCoverI;
        }

        /**
         * 
         * @param scenario
         * @return C/(I+N)
         * @throws Exception
         */
        private double getCoverNplusI(ScenarioInfo scenario) throws Exception {
                double CoverN = 0; // Initialise
                CoverN = 10 * Math.log10(Math.pow(10, ((singleResult.dRSS) / 10))
                                / ((Math.pow(10, (singleResult.iRSS / 10)) + Math.pow(10,
                                                (singleResult.noiseFloor / 10)))));

                return CoverN;
        }

        /**
         * 
         * @return protection criterion to be used for calculation
         */
        private double getCriterionLimit() {
                switch (criterionIndex) {
                        case 0:
                                return rCoverI;
                        case 1:
                                return rCoverN;
                        case 2:
                                return rIoverN;
                        default:
                                return (rCoverN);
                }
        }

        /**
         * 
         * @return highest CoverI
         */
        private double getHighestCoverI() {
                double highest = -100;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (simulatedResults.get(i).cOverI > highest) {
                                highest = simulatedResults.get(i).cOverI;
                        }
                }
                return highest;
        }

        /**
         * 
         * @return highest CoverN
         */
        private double getHighestCoverN() {
                double highest = -100;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (simulatedResults.get(i).cOverN > highest) {
                                highest = simulatedResults.get(i).cOverN;
                        }
                }
                return highest;
        }

        /**
         * 
         * @return highest dRSS
         */
        private double getHighestDRSS() {
                double highest = -100;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (simulatedResults.get(i).dRSS > highest) {
                                highest = simulatedResults.get(i).dRSS;
                        }
                }
                return highest;
        }

        /**
         * 
         * @param scenario
         * @return I/N
         */
        private double getIoverN(ScenarioInfo scenario) {
                double rIoverN = 10 * Math.log10(((Math.pow(10,
                                (singleResult.iRSS / 10)) + Math.pow(10,
                                (singleResult.noiseFloor / 10)))));

                rIoverN = 10 * Math.log10(((Math.pow(10, (minDRSS / 10)) + Math.pow(10,
                                (singleResult.noiseFloor / 10)))));

                return rIoverN;
        }

        /**
         * 
         * @param i
         *            index of current location
         * @return protection criterion exceeded or not
         */
        private boolean getLimitExceeded(int i) {
                boolean isInterfered = false;
                switch (criterionIndex) {
                        case 0: { // C/I
                                if (simulatedResults.get(i).dRSS < (simulatedResults.get(i).iRSS + rCoverI)
                                                && simulatedResults.get(i).dRSS > minDRSS) {
                                        simulatedResults.get(i).isInterfered = true;
                                        isInterfered = true; // exceeded
                                }
                                break;
                        }
                        case 1: {// C/(I+N)
                                if (simulatedResults.get(i).dRSS < (simulatedResults.get(i).iRSS + rCoverN)
                                                && simulatedResults.get(i).dRSS > minDRSS) {
                                        simulatedResults.get(i).isInterfered = true;
                                        isInterfered = true; // exceeded
                                }
                                break;
                        }
                        case 2: {// I/N
                                if (simulatedResults.get(i).iRSS >= (simulatedResults.get(i).noiseFloor + rIoverN)
                                                && simulatedResults.get(i).dRSS > minDRSS) {
                                        simulatedResults.get(i).isInterfered = true;
                                        isInterfered = true; // exceeded
                                }
                                break;
                        }
                        default:
                                isInterfered = false;

                }
                return isInterfered;
        }

        private boolean getLimitExceeded(int i, double sum) {
                boolean isInterfered = false;
                switch (criterionIndex) {
                        case 0: { // C/I
                                if (simulatedResults.get(i).dRSS < (sum + rCoverI)
                                                && simulatedResults.get(i).dRSS > minDRSS) {
                                        simulatedResults.get(i).isInterfered = true;
                                        isInterfered = true; // exceeded
                                }
                                break;
                        }
                        case 1: {// C/(I+N)
                                double includeNoise = 10 * Math.log10(Math.pow(10, (sum / 10))
                                                + Math.pow(10,
                                                                (simulatedResults.get(i).noiseFloor / 10)));
                                if (simulatedResults.get(i).dRSS < (includeNoise + rCoverN)
                                                && simulatedResults.get(i).dRSS > minDRSS) {
                                        simulatedResults.get(i).isInterfered = true;
                                        isInterfered = true; // exceeded
                                }
                                break;
                        }
                        case 2: {// I/N
                                if (sum >= (simulatedResults.get(i).noiseFloor + rIoverN)
                                                && simulatedResults.get(i).dRSS > minDRSS) {
                                        simulatedResults.get(i).isInterfered = true;
                                        isInterfered = true; // exceeded
                                }
                                break;
                        }
                        default:
                                isInterfered = false;

                }
                return isInterfered;
        }

        /**
         * {@literal this method is taken from the propagation model P1546-3}
         * 
         * @param x
         *            locationProbability
         * @return correction factor
         */
        private double getLocationProbabilityFactor(double x) throws Exception {
                double Q, t, xi;
                double c0, c1, c2, d1, d2, d3;
                x /= 100;
                try {
                        if (x > 0.5) {
                                x = 1 - x;
                        }
                        c0 = 2.515517;
                        c1 = 0.802853;
                        c2 = 0.010328;
                        d1 = 1.432788;
                        d2 = 0.189269;
                        d3 = 0.001308;

                        t = Math.sqrt((-2 * Math.log(x)));
                        xi = (((c2 * t + c1) * t) + c0)
                                        / (((d3 * t + d2) * t + d1) * t + 1);
                        if (x <= 0.5) {
                                Q = t - xi;
                        } else {
                                Q = -(t - xi);
                        }
                        return Q;
                } catch (Exception e) {
                        throw new Exception(e.getMessage());
                }
        }

        /**
         * 
         * @return lowest CoverI
         */
        private double getLowestCoverI() {
                double lowest = 1000;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (simulatedResults.get(i).cOverI < lowest) {
                                lowest = simulatedResults.get(i).cOverI;
                        }
                }
                return lowest;
        }

        /**
         * 
         * @return lowest CoverN
         */
        private double getLowestCoverN() {
                double lowest = 100;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (simulatedResults.get(i).cOverN < lowest) {
                                lowest = simulatedResults.get(i).cOverN;
                        }
                }
                return lowest;
        }

        /**
         * 
         * @return lowest dRSS
         */
        private double getLowestDRSS() {
                double lowest = 100;
                for (int i = 0; i < simulatedResults.size(); i++) {
                        if (simulatedResults.get(i).dRSS < lowest) {
                                lowest = simulatedResults.get(i).dRSS;
                        }
                }
                return lowest;
        }

        /**
         * 
         * @return lowest level not zero
         */
        private double getLowestLPnotZero() {
                double[] tLP = new double[rLP.size()]; // leaves the order of the global rLP unchanged
                for (int i = 0; i < tLP.length; i++) {
                        tLP[i] = rLP.get(i);
                }
                Arrays.sort(tLP);

                int i = -1; // increased by 1 entering the loop
                do {
                        i++;
                } while (tLP[i] <= 0);
                double lowest = tLP[i];
                return lowest;
        }

        /**
         * {@literal defines the size and scales the graph}
         */
        private void scaleFigure() {
                StdDraw.setCanvasSize(900, 900);
                StdDraw.setXscale((-1.2) * maxDistance, 1.2 * maxDistance);
                StdDraw.setYscale((-1.2) * maxDistance, 1.2 * maxDistance);
        }

        /**
         * {@literal this method has been derived from a so called iterative approach}
         * 
         * @param deltaFactor2
         * @return corresponding location probability
         */
        private double getPercentageSevenTrials(double deltaFactor2) {

                double rPmid = 0;
                double rProbabilityFactor = 0;
                double rPmin = 0;
                double rPmax = 99.999;
                double erfcMax = 5;
                double erfcMin = 0;
                try {
                        erfcMax = getLocationProbabilityFactor(rPmax);
                } catch (Exception e1) {
                        e1.printStackTrace();
                }
                erfcMin = -erfcMax; // symmetrical
                try { // locationProbability is reference
                        rProbabilityFactor = getLocationProbabilityFactor(locationProbability);
                } catch (Exception e1) {
                        e1.printStackTrace();
                }
                double delta = deltaFactor2 + rProbabilityFactor;
                if (delta > erfcMax) {
                        return rPmax; // limits the valid range
                } else if (delta < erfcMin) {
                        return (100 - rPmax);
                } else {
                        double erfc = 0;
                        while (true) { // endless loop
                                rPmid = (rPmax - rPmin) / 2 + rPmin;
                                try {
                                        erfc = getLocationProbabilityFactor(rPmid);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                                if (delta < 0)
                                        erfc *= -1;
                                if (erfc < erfcMin)
                                        erfc = erfcMin;
                                if (Math.abs(erfc - delta) < 0.001) {
                                        break; // leaves the loop
                                } else {
                                        if (erfc < delta) {
                                                rPmin = rPmid;
                                        } else
                                                rPmax = rPmid;
                                }
                        }
                        return rPmid;
                }
        }

        /**
         * @return the numberOfPixelsBelowLP
         */
        private int getNumberOfPixelsBelowLP() {
                return numberOfPixelsBelowLP;
        }

        /**
         * @param numberOfPixelsBelowLP
         *            the numberOfPixelsBelowLP to set
         * @param scenario
         */
        private void setNumberOfPixelsBelowLP(ScenarioInfo scenario) {
                try {
                        this.numberOfPixelsBelowLP = getNumberOfPixelsEmpty(scenario);
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }

        /**
         * @return the numberOfPixelsInterfered
         */
        private int getNumberOfPixelsInterfered() {
                return numberOfPixelsInterfered;
        }

        /**
         * @param numberOfPixelsInterfered
         *            the numberOfPixelsInterfered to set
         * @param scenario
         */
        private void setNumberOfPixelsInterfered(ScenarioInfo scenario) {
                this.numberOfPixelsInterfered = getNumberOfPixelsInterfered(scenario);
        }

        /**
         * @return the numberOfEventsToBeConsidered
         */
        private int getNumberOfEventsToBeConsidered() {
                return numberOfEventsToBeConsidered;
        }

        /**
         * @param numberOfEventsToBeConsidered
         *            the numberOfEventsToBeConsidered to set
         */
        private void setNumberOfEventsToBeConsidered(ScenarioInfo scenario) {
                this.numberOfEventsToBeConsidered = scenario.getTotalNumberOfEvents()
                                - scenario.getNumberOfInterferingLinks();
        }
}

/*-------------------------------------*/

class CollectedData {
        int event;
        double x;
        double y;
        double dRSS;
        double iRSS;
        int ilk;
        double cOverN;
        double cOverI;
        double cIverN;
        double noiseFloor;
        boolean isMultipleILK;
        boolean isInterfered;
}

class ProgressBarStoreFile {
        JProgressBar progressBar;
        JFrame frame;

        public ProgressBarStoreFile(String label) {
                this.frame = new JFrame(label);
                this.progressBar = new JProgressBar(0, 100);
        }

        public void init() {
                int width = 400;
                int height = 50;
                progressBar.setStringPainted(true);
                progressBar.setForeground(new Color(200, 200, 50));
                frame.setSize(width, height);
                frame.setLocationRelativeTo(null);
                frame.setResizable(false);
                frame.getContentPane().add(progressBar);
                frame.setVisible(true);
        }

        public void stop() {
                frame.dispose();
                frame.setVisible(false);
        }
}